#include<stdio.h>
#include<stdlib.h>


// Globally declared variables
//FILE *fp;


// Linked List Structure defined
typedef struct linkedlist_node
{
	void * key;
	void * data;
	struct linkedlist *next;
}l_node;

/*
// Functions declared
l_node * createl_node();
int displayOperations();
l_node *performOperation(int choice, l_node *start);
l_node *insertl_nodeAtBeginning(l_node *start, void *nodeData);
l_node *insertl_nodeSortedOrder(l_node *start, void *nodeData, char *filename);
l_node *deletel_nodeAtBeginning(l_node *start);
l_node *deletel_node(l_node *start, void *data);
void display(l_node *start);
l_node *getByStringKey(l_node *start, char* filename, h_node **data[]);
*/




// Initially, we'll read the data from the file, and we'll create a Linked List out of it
l_node *readFromFile();
void insert(l_node * start, int a);


//Inserting node at beginning
l_node *insertl_nodeAtBeginning(l_node *start, void *ptr_nodeData);//make void * for nodeData


//Displaying LinkedList from RAM
l_node *displayLinkedList(l_node *start);


//Write to File (Persistent Storage)
void writeToFile(l_node *start);


//Calling various Performing functions 
l_node *performOperation(int choice, l_node *start);


//Displaying the various operations
int displayOperations();


//Deleting a node from Linked List
//l_node *deletel_node(l_node *start);
l_node *deletel_node(l_node *start, void *ptr_nodeData);


//Searching in Linked List
l_node *searchl_node(l_node *start, void *ptr_nodeData);




//creating new Node for linked list
l_node * createl_node()
{
	l_node *newNode = (l_node *)malloc(sizeof(l_node));
	if(!newNode)	// System runs out of memory
	{
		printf("Operation terminated! Unable to allocate Memory.");
		return;
	}
	return newNode;
}




// Reading from Persistent Data Storage
l_node *readFromFile()
{
	int a;
	int count=0;
	l_node *p, *q, *start, *tempNode;
	start=NULL;

	FILE *fpRead;
	fpRead=fopen("Desktop:\\lltry\\TestPersistentStorage.txt", "rb");
	while(fread(&a, sizeof(int), 1, fpRead))
	{
			count++;
			if(count==1)
			{
				
				start=createl_node();
				start->data=a;
				start->next=NULL;
			}
			else
			{
				insert(start, a);				
			}	
			count++;			
	}
		
	if(count!=0)
	{
		printf("\nThe linked list read from Binary File is:  \n");
		tempNode=start;
		while(tempNode!=NULL)
		{
			printf("%d  ", tempNode->data);
			tempNode=tempNode->next;
		}	
	}
	else
	{
		printf("\nNo data present in the FILE");
	}
	
	fclose(fpRead);		
	
	return start;
}



void insert(l_node * start, int a)  // Reading data from file one by one and creating a LL out of it
{
	l_node *p;
	p=createl_node();
	p->data=a;
	p->next=NULL;
	while(start->next!=NULL)
	{
		start=start->next;
	}
	start->next=p;
}





//Write to File (Persistent Storage)
void writeToFile(l_node *start)
{
	int a;
	FILE *fpWrite;
	fpWrite=fopen("Desktop:\\lltry\\TestPersistentStorage.txt", "wb");
	
	//printf("---Testing writeToFile----> file opened successfully");
	
	while(start!=NULL)
	{
		a=start->data;
		fwrite(&a, sizeof(int), 1, fpWrite);
		start=start->next;
	}
	//printf("Succesfully written to Persistent File");
	
	fclose(fpWrite);
}





//Displaying Linked List just from RAM, and not from FILE
l_node *displayLinkedList(l_node *start)
{
	l_node *tempNode = start;
	if(tempNode!=NULL)
	{
		printf("The Linked List is:  ");
		while(tempNode!=NULL)
		{
			printf("%d   ", tempNode->data);
			tempNode=tempNode->next;
		}
	}
	else
	{
		printf("\nNo node exist in the Linked List");
	}
	return start;
}





//insertl_node (at beginning)
l_node *insertl_nodeAtBeginning(l_node *start, void *ptr_nodeData) //make nodeData as void *
{
	l_node *newNode = createl_node();
	newNode->data=*((int *)ptr_nodeData);
	if(start==NULL)
	{
		newNode->next=NULL;		
	}
	else
	{
		newNode->next=start;		
	}
	start=newNode;
	
	printf("\nThe node has been added successfully!\n");
	
	//displaying ameneded Linked List from RAM only
	start=displayLinkedList(start);	
	return start;	
}




//Deleting Node from Linked List
l_node *deletel_node(l_node *start, void *ptr_nodeData)
{
	l_node *preNode, *currentNode;
	currentNode=start;
	int keepData;
	keepData= *(int *)ptr_nodeData;
	if(currentNode->data==keepData)
	{
		preNode=currentNode->next;
		free(currentNode);
		start=preNode;
	}
	else
	{
		while(currentNode->data!=keepData && currentNode->next!=NULL)
		{
			preNode=currentNode;
			currentNode=currentNode->next;
		}
		
		if(currentNode->data == keepData)
		{
			preNode->next=currentNode->next;
			free(currentNode);			
		}
		else
		{
			printf("\nOperation Terminated! \nThe node data you entered, doesn't exist in the Linked List.");
			return start;
		}
	}
	printf("\nThe node is deleted successfully!\n");
	
	start=displayLinkedList(start);
	
	return start;	
}




//Searching Data in Linked List
l_node *searchl_node(l_node *start, void *ptr_nodeData)
{
	int count=1;
	l_node *tempNode;
	tempNode=start;
	while(tempNode->data!=*(int *)ptr_nodeData && tempNode->next!=NULL)
	{
		tempNode=tempNode->next;
		count++;
	}
	if(tempNode->data == *(int *)ptr_nodeData)
	{
		printf("\nSearch Successful! \nThe position of the node is:  %d\n", count);
	}
	else
	{
		printf("\nOperation Terminated! \nNo such node exist in the Linked List");
	}
	
	return start;
}





//Calling various Performing functions 
l_node *performOperation(int choice, l_node *start)
{
	int nodeData;
	void *ptr_nodeData;
	switch(choice)
	{
		case 1:
			printf("\nEnter data you wish to insert:");
			scanf("%d", &nodeData);
			ptr_nodeData = (void*)&nodeData;
			start = insertl_nodeAtBeginning(start, ptr_nodeData);
			break;
			
		case 2:
			//insert node in sorted order (for hah table)
			
			break;
		
		
		case 3:
			printf("Enter the node you wish to delete:  ");
			scanf("%d", &nodeData);
			ptr_nodeData = (void *)&nodeData;
			start = deletel_node(start, ptr_nodeData);
			break;			
		
		case 4:
			start = displayLinkedList(start);
			break;
			
				
		case 5:
			printf("\nEnter the nodeData you wish to search:  ");
			scanf("%d", &nodeData);
			ptr_nodeData=(void *)&nodeData;
			start = searchl_node(start, ptr_nodeData);
			break;
		
			
		default:
			printf("Invalid entry!.. Exiting the current operation.");
	}
	return start;
}



//Displaying the various operations
int displayOperations()
{
	int choice;
	printf("1. Insert node at Beginning\n");
	printf("2. InsertInSortedOrder (Currently Out of order)\n");
	printf("3. Delete\n");
	printf("4. Display\n");
	printf("5. Search");
	printf("\nEnter your choice:  ");
	scanf("%d", &choice);
	return choice;
}


//Main Function Starts
void main()
{
	int choice;
	int kontinue=1;
	l_node *start=readFromFile();
	while(kontinue==1)
	{
		printf("\nOperations you wish to perform:  \n");
		choice = displayOperations();
		
		start=performOperation(choice, start);
		
		printf("\nPress 1 to continue, or else any number to exit:");
		scanf("%d", &kontinue);
	}
	
	//writing back full linked list (amended or not), into persistent FILE
	writeToFile(start);
}
